#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>

#include <sys/time.h>
#include <sys/resource.h>
#include "../Comm/Log.hpp"
#include "../Comm/Util.hpp"
using namespace ns_util;
class Runner
{
public:
    Runner()
    {
    }
    static void SetProcLimit(int cpu_limit, int mem_limit)
    {
        // 设置cpu使用时间
        struct rlimit cpu;
        cpu.rlim_cur = cpu_limit;
        cpu.rlim_max = RLIM_INFINITY;
        setrlimit(RLIMIT_CPU, &cpu);

        // 限制空间
        struct rlimit mem;
        mem.rlim_cur = mem_limit * 1024;
        mem.rlim_max = RLIM_INFINITY;
        setrlimit(RLIMIT_AS, &mem);
    }
    static int Run(const std::string &file_name, int cpu_limit, int mem_limit)
    {
        umask(0);
        std::string exe = Pathutil::Exe(file_name);
        std::string stdin = Pathutil::Stdin(file_name);
        std::string stdout = Pathutil::Stdout(file_name);
        std::string stderr = Pathutil::Stderr(file_name);

        int _stdin_fd = open(stdin.c_str(), O_CREAT | O_RDWR, 0664);
        int _stdout_fd = open(stdout.c_str(), O_CREAT | O_WRONLY, 0664);
        int _stderr_fd = open(stderr.c_str(), O_CREAT | O_WRONLY, 0664);
        if (_stdin_fd < 0 || _stdout_fd < 0 || _stderr_fd < 0)
        {
            LOG(ERROR) << "runner:创建文件失败" << "\n";
            return -1;
        }
        int pid = fork();
        if (pid < 0)
        {
            LOG(ERROE) << "runner:创建子进程失败" << "\n";
            close(_stdin_fd);
            close(_stdout_fd);
            close(_stderr_fd);
            return -2;
        }
        else if (pid == 0)
        {
            dup2(_stdin_fd, 0);
            dup2(_stdout_fd, 1);
            dup2(_stderr_fd, 2);
            SetProcLimit(cpu_limit, mem_limit);
            execl(exe.c_str() /*我要执行谁*/, exe.c_str() /*我在命令行上如何执行*/, nullptr);
            LOG(ERROE) << "ruuner:进程替换失败" << "\n";
            exit(0);
        }
        else
        {
            int status = 0;
            waitpid(pid, &status, 0);
            close(_stdin_fd);
            close(_stdout_fd);
            close(_stderr_fd);
            LOG(INFO) << "运行成功......" << "\n";
            return status & 0x7f;
        }
    }

    ~Runner()
    {
    }
};